﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Q7.BevTree
{
    public class BevNode
    {
        #region Const
        public const int BRS_EXECUTING = 0;
        public const int BRS_FINISH = 1;
        public const int BRS_ERROR_TRANSITION = -1;

        public const int MAX_CHILDREN = 16;
        #endregion

        #region Prop
        //protected string _debugName;
        //protected BevNodePrecondition _precondition;
        //protected List<BevNode> _children;
        //protected BevNode _parent;

        public string DebugName { get; set; }

        public List<BevNode> Children
        {
            get; set;
        }

        public BevNode Parent
        {
            get; set;
        }

        public BevNodePrecondition Precondition
        {
            get; set;
        }
        #endregion

        public BevNode(string debugName = null)
        {
            DebugName = debugName;
        }

        /// <summary>
        /// 添加行为子节点
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public BevNode AddChild(BevNode node)
        {
            if (Children == null)
                Children = new List<BevNode>();

            if (Children.Count == MAX_CHILDREN)
                throw new Exception("overflow, max children number is " + MAX_CHILDREN);

            Children.Add(node);
            node.Parent = this;
            return this;
        }

        /// <summary>
        /// 插入一个子节点到指定索引
        /// </summary>
        /// <param name="node"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public BevNode AddChildAt(BevNode node, int index)
        {

            this.AddChild(node);

            if (index < 0)
                index = 0;
            else if (index > Children.Count - 1)
                index = Children.Count;

            for (int i = Children.Count; i > index; i--)
            {
                Children[i] = Children[i - 1];
            }

            Children[index] = node;

            return this;
        }

        /// <summary>
        /// 设置前提条件
        /// </summary>
        /// <param name="precondition"></param>
        /// <returns></returns>
        public BevNode SetPrecondition(BevNodePrecondition precondition)
        {
            Precondition = precondition;
            return this;

        }

        /// <summary>
        /// 节点是否执行
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public bool Evaluate(BevNodeInputParam input)
        {
            var ret = Precondition == null || Precondition.Evaluate(input);
            return ret && DoEvaluate(input);
        }

        /// <summary>
        /// 跳转到另一个节点
        /// </summary>
        /// <param name="input"></param>
        public void Transition(BevNodeInputParam input)
        {
            DoTransition(input);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <param name="output"></param>
        /// <returns></returns>
        public int Tick(BevNodeInputParam input, BevNodeOutputParam output)
        {
            return DoTick(input, output);
        }

        /// <summary>
        /// 内部前提
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        protected virtual bool DoEvaluate(BevNodeInputParam input)
        {
            return true;
        }

        protected virtual void DoTransition(BevNodeInputParam input)
        {
            // nothing to do ... implement yourself
        }

        protected virtual int DoTick(BevNodeInputParam input, BevNodeOutputParam output)
        {
            return BRS_FINISH;
        }

        public bool CheckIndex(int i)
        {
            return i > -1 && i < Children.Count;
        }
    }
}
